<template>
  <view class="wrapper" :style="[itemStyle]">
    <!-- 在nvue中，image图片的宽度默认为屏幕宽度，需要通过flex:1撑开，另外必须设置高度才能显示图片 -->
    <image
      v-if="baseInfo.type === 'image'"
      class="image"
      :src="baseInfo.url"
      :mode="imgMode"
      :style="{ height, width: '100%', borderRadius: radius }"
      @click="clickHandler(index)"
    ></image>
    <video
      v-if="baseInfo.type === 'video'"
      :id="videoId"
      class="video"
      :enableProgressGesture="false"
      showCenterPlayBtn
      :src="baseInfo.url"
      :poster="baseInfo.poster"
      :title="baseInfo.title"
      :style="{ height, width: '100%' }"
      controls
      @click="clickHandler(index)"
      @play="onPlay"
      @pause="onPause"
    ></video>
    <text v-if="baseInfo.title && !videoPlay" class="ellipsis title" :style="[titleStyle]">
      {{ baseInfo.title }}
    </text>
  </view>
</template>

<script lang="ts" setup>
  import { type CSSProperties, type PropType, computed, getCurrentInstance, nextTick, ref, watch } from 'vue';
  import type { $SizeUnitStr } from '@/mxp-ui/mxp-tool/types/interface';
  import { verifyVideoUrl } from '@/mxp-ui/mxp-tool/utils/verify';
  import { getOnlyID } from '@/mxp-ui/mxp-tool/utils/common';
  import type { ImageMode } from 'mxp-uni-types';
  defineOptions({
    name: 'mxp-swiper-item',
  });

  const props = defineProps({
    /** 下标 */
    index: { type: Number, required: true },
    /** 可为字符串和对象，如为对象可通过 urlKey posterKey sourceTypeKey titleKey 指定目标属性名 */
    item: { type: [Object, String] as PropType<Record<string, unknown> | string>, required: true },
    /** 当前显示swiper的下标 */
    currentIndex: { type: Number, required: true },
    /** 当 list 为对象时，视频或图片链接的 key */
    urlKey: { type: String, required: true },
    /** 当 list 为对象时，且为视频时，视频封面海报的 key */
    posterKey: { type: String, required: true },
    /** 当 list 为对象时，显示标题的 key */
    titleKey: { type: String, required: true },
    /** 当 list 为对象时，资源类型的 key ，默认默认，值为 undefined ，即：通过 url 去判断资源类型，注意：资源类型只能为 image 或 video， */
    sourceTypeKey: { type: String, default: undefined },
    /** 前边距，可用于露出前一项的一小部分，nvue和支付宝不支持 */
    previousMargin: { type: String as PropType<$SizeUnitStr>, required: true },
    /** 后边距，可用于露出后一项的一小部分，nvue和支付宝不支持 */
    nextMargin: { type: String as PropType<$SizeUnitStr>, required: true },
    /** 当滚动到视频页时是否自动播放 */
    videoAutoplay: { type: Boolean, required: true },
    /** 图片的裁剪模式 */
    imgMode: { type: String as PropType<ImageMode>, required: true },
    /** 组件高度 */
    height: { type: String as PropType<$SizeUnitStr>, required: true },
    /** 组件圆角，数值或带单位的字符串 */
    radius: { type: String as PropType<$SizeUnitStr>, required: true },
    /** 是否显示标题，要求数组对象中有title属性 */
    showTitle: { type: Boolean, required: true },
    /** 显示的标题样式 */
    titleStyle: { type: Object as PropType<CSSProperties>, required: true },
  });
  const emits = defineEmits<{
    (e: 'click', val: any): void;
    (e: 'videoPlayChange', val: boolean): void;
  }>();
  const videoId = getOnlyID('video');
  const videoPlay = ref(false);
  const instance = getCurrentInstance();

  let video: UniApp.VideoContext | undefined = undefined;
  const baseInfo = computed<{ type: string; url: string; poster: string; title: string }>(() => {
    if (typeof props.item === 'string') {
      return { type: verifyVideoUrl(props.item) ? 'video' : 'image', url: props.item, poster: '', title: '' };
    } else if (typeof props.item === 'object') {
      const url = props.urlKey && props.item[props.urlKey] ? String(props.item[props.urlKey]) : '';
      return {
        url,
        type: props.sourceTypeKey && props.item[props.sourceTypeKey] ? String(props.item[props.sourceTypeKey]) : verifyVideoUrl(url) ? 'video' : 'image',
        poster: props.posterKey && props.item[props.posterKey] ? String(props.item[props.posterKey]) : '',
        title: props.showTitle && props.titleKey && props.item[props.titleKey] ? String(props.item[props.titleKey]) : '',
      };
    } else {
      return { type: '', url: '', poster: '', title: '' };
    }
  });
  const itemStyle = computed(() => {
    const style: CSSProperties = {};
    // #ifndef MP-TOUTIAO
    // 左右流出空间的写法不支持nvue和头条
    // 只有配置了此二值，才加上对应的圆角，以及缩放
    if (parseInt(props.nextMargin) && parseInt(props.previousMargin)) {
      style.borderRadius = props.radius;
      if (props.index !== props.currentIndex) {
        style.transform = 'scale(0.92)';
      }
    }
    // #endif
    return style;
  });

  watch(
    () => props.currentIndex,
    (val) => {
      if (baseInfo.value.type === 'video') {
        nextTick(() => {
          try {
            video = video || uni.createVideoContext(videoId, instance);
            if (props.index === val) {
              // 当视频显示时，自动播放
              props.videoAutoplay && video.play();
            } else {
              // 当视频隐藏时，暂停播放
              video.pause();
            }
          } catch (e) {
            console.error('关闭视频失败', e);
          }
        });
      }
    }
  );

  /**
   * 点击某个item
   */
  function clickHandler(index: number) {
    emits('click', index);
  }

  /** 视频播放 */
  function onPlay() {
    emits('videoPlayChange', true);
    videoPlay.value = true;
  }
  /** 视频播放 */
  function onPause() {
    emits('videoPlayChange', false);
    videoPlay.value = false;
  }
</script>

<style lang="scss" scoped>
  .mxp-swiper-item {
    flex: 1;
    min-width: 30px;

    .wrapper {
      position: relative;
      display: flex;
      flex: 1;
      overflow: hidden;
      transition: transform 0.3s;

      .image {
        flex: 1;
        width: 100%;
      }

      .video {
        flex: 1;
        width: 100%;
      }

      .title {
        position: absolute;
        right: 0;
        bottom: 0;
        left: 0;
        flex: 1;
        height: 30px;
        font-size: 14px;
        line-height: 30px;
        color: #ffffff;
        background-color: rgba(0, 0, 0, 0.3);
      }
    }

    .ellipsis {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
</style>
